#include "CanReaper.h"
#include "CanSender.h"
#include "LoggerConfigs.h"
#include "utils.hpp"

#include <linux/can.h>
#include <utility>
#include <format>


namespace canpp {
    using std::move;
    using std::vformat;
    using std::make_format_args;
    using std::format_args;

    CanSender::~CanSender() {
        logger.force_flush();
    }

    CanSender::CanSender(string &&canInterface, optional<string> &&id): logger([&] {
                                                                            const string real_id = id.value_or(
                                                                                std::to_string(random_number(0, 2000)));
                                                                            string LOG_DIR =
                                                                                    string(CANPP_LOG_DIR) +
                                                                                    "/CanSenders/CanSender_"
                                                                                    + real_id;
                                                                            const string LOGGER_NAME =
                                                                                    "CanSender_" + real_id;
                                                                            const string log_config = vformat(
                                                                                senderLoggerConfig
                                                                                , format_args(
                                                                                    make_format_args(LOG_DIR)));

                                                                            return log::create_log(
                                                                                LOGGER_NAME, log_config);
                                                                        }()),
                                                                        interface(std::move(canInterface)),
                                                                        id(id.value_or(
                                                                            std::to_string(random_number(0, 2000)))) {
        fd = CanReaper::getInstance().createOrGetInterfaceFd(interface);
        logger.info(format("CanSender: {} initialized on {}!", this->id, this->interface));
    }

    CanSender::CanSender(const string &canInterface, const optional<string> &id
    ): CanSender(string(canInterface), optional(id)
    ) {
    }

    void CanSender::canSend(const can_frame &&frame) const {
        const can_frame frame_ = frame;
        if (write(fd, &frame_, sizeof(frame_)) == -1) {
            LOG_ERROR_AND_QUIT(logger, "CanSend failed: " + string(strerror(errno)));
        }
        logger.info(
            format("Message sent : {}", format_frame_data(frame_)));
        // log::get_log_by_name((LOGGER_NAME)).debug("Sending from fd:{}", fd);
    }
} // canpp
